package jumpingnotes.dao.hibernate;

import java.util.List;

import jumpingnotes.dao.GenericDao;
import jumpingnotes.util.Sorter;
import jumpingnotes.util.SorterHelper;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class GenericHibernateDao<T> extends HibernateDaoSupport implements GenericDao<T>
{
	private Class<T> persistentClass;

	public GenericHibernateDao(Class<T> persistentClass)
	{
		this.persistentClass = persistentClass;
	}

	public Class<T> getPersistentClass()
	{
		return persistentClass;
	}

	@SuppressWarnings("unchecked")
	public T findById(int id)
	{
		return (T) getHibernateTemplate().get(getPersistentClass(), id);
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll(final T exampleEntity, final int firstResult, final int maxResults, final Sorter sorter)
	{
		return (List) getHibernateTemplate().execute(new HibernateCallback()
		{
			public Object doInHibernate(Session session) throws HibernateException
			{
				Criteria criteria = session.createCriteria(getPersistentClass());
				if (exampleEntity != null)
					criteria.add(Example.create(exampleEntity).excludeZeroes().enableLike());
				if (sorter != null)
					SorterHelper.addSorter(criteria, sorter);
				if (firstResult >= 0)
					criteria.setFirstResult(firstResult);
				if (maxResults > 0)
					criteria.setMaxResults(maxResults);
				return criteria.list();
			}
		});
	}

	public List<T> findAll(T exampleEntity, int firstResult, int maxResults)
	{
		return findAll(exampleEntity, firstResult, maxResults, null);
	}

	public List<T> findAll(T exampleEntity, Sorter sorter)
	{
		return findAll(exampleEntity, -1, -1, sorter);
	}

	public List<T> findAll(T exampleEntity)
	{
		return findAll(exampleEntity, -1, -1, null);
	}

	public List<T> findAll(int firstResult, int maxResults, Sorter sorter)
	{
		return findAll(null, firstResult, maxResults, sorter);
	}

	public List<T> findAll(int firstResult, int maxResults)
	{
		return findAll(null, firstResult, maxResults, null);
	}

	public List<T> findAll(Sorter sorter)
	{
		return findAll(null, -1, -1, sorter);
	}

	public List<T> findAll()
	{
		return findAll(null, -1, -1, null);
	}

	public int save(T entity)
	{
		return (Integer) getHibernateTemplate().save(entity);
	}

	public void update(T entity)
	{
		getHibernateTemplate().update(entity);
	}

	public void delete(T entity)
	{
		getHibernateTemplate().delete(entity);
	}

	public void delete(int id)
	{
		T entity = findById(id);
		delete(entity);
	}
}
